home *** CD-ROM | disk | FTP | other *** search
/ 130 MIDI Tool Box / 130 MIDI Tool Box.iso / kbs / kbs.pas
Pascal/Delphi Source File  |  1987-07-27  |  9KB  |  343 lines

  1. program KawaiBankSaver;
  2. {
  3. Saves internal bank from K3 to disk file and restores it.
  4.   NOTE: there are several subroutines that were used for debugging, etc
  5.         and have no current implementation.
  6. }
  7.  
  8. const
  9.   dataport = $330;                  {These are port addresses for the}
  10.   statport = $331;                  {IBM version of the MPU-401      }
  11.   drs = $80;                        {They must be changed for other  }
  12.   drr = $40;                        {machines                        }
  13.   ack = $fe;
  14.  
  15.   BytesPerPatch = 34; {Patch consists of 34 bytes + chksum}
  16.   PatchesPerBank= 50; {each bank has 50 patches}
  17.   Banks         =  2; {There are two banks}
  18.  
  19. type
  20.   str1 = string[1];
  21.   str2 = string[2];
  22.   str8 = string[8];
  23.   AnyStringType=String[255];
  24.   PatchType = array[1.. BytesPerPatch] of Byte;
  25.   BankType = array[1..PatchesPerBank] of PatchType;
  26.  
  27.   {Kawai stuff}
  28.  
  29. var
  30.   EscAbort:Boolean;
  31.   j,MidiData: byte;
  32.   Direction:Char;
  33.  
  34. procedure GetData (var MidiData:byte);  {Get one byte from MPU}
  35.   var
  36.     j:byte;
  37.   begin
  38.    j := 0;
  39.    repeat                               {Loop until Data Ready to Receive}
  40.      j := port[statport];               {has correct value; then get     }
  41.    until (j and drs) = 0;               {MidiData from DataPort          }
  42.    MidiData := port [dataport];
  43.   end;
  44.  
  45. procedure PutData (MidiData:byte);  {Puts one byte to MPU}
  46.   begin
  47.     j := 0;
  48.     repeat                          {Loop until Data Ready to Send   }
  49.       j := port [statport]          {has correct value; then send    }
  50.     until (j and drr) = 0;          {MidiData to DataPort            }
  51.     port [dataport] := MidiData;
  52.     repeat
  53.       GetData(j);
  54.     until (j = ack);
  55.   end;
  56.  
  57. procedure PutCmd (cmd:byte);            {Sends command to MPU}
  58. begin
  59.   j := 0;
  60.   repeat                              {Loop until Data Ready to Receive}
  61.     j := port [statport];             {has correct value; then send    }
  62.   until (j and drr) = 0;              {command to MPU                  }
  63.   port [statport] := cmd;
  64.   repeat                              {Wait in loopuntil MPU send byte }
  65.     GetData(j);                       {to acknowledge receipt of command}
  66.   until j = ack;
  67. end;
  68.  
  69. function Hex(b:byte):str2;
  70. const
  71.   h : array [0..15] of char = '0123456789ABCDEF';
  72. begin
  73.   Hex := h [b shr 4] + h [b and 15];
  74. end;
  75.  
  76. Function Bin (Val:Byte):Str8;
  77. Var
  78.   Mask:Byte;
  79.   Hold:Str8;
  80. Begin
  81.   Hold:='';
  82.   Mask:=$80;
  83.   Repeat
  84.     Hold := Hold + Chr(48 + ord( (Val and Mask) > 0 ) );
  85.     Mask := Mask shr 1;
  86.   Until Mask=0;
  87.   Bin := Hold;
  88. End;
  89.  
  90. Function Int2Str(I:Integer):AnyStringType;
  91. Var
  92.   Temp:AnyStringType;
  93. Begin
  94.   Str(I,Temp);
  95.   Int2Str:=Temp;
  96. End;
  97.  
  98. Procedure Info(Phrase:anystringtype);
  99. Begin
  100.   GotoXY(1,25);
  101.   Write(Con,Phrase);
  102.   ClrEOL;
  103. End;
  104.  
  105. Function MergeBytes(Hi,Lo:Byte):Byte;
  106. { The result is the low nibble of Hi moved to the high nibble, plus
  107.                 the low nibble of Lo.
  108.  
  109.   ie:     ---Hi--- and ---Lo--- yield  Merge2Bytes
  110.    bin:   0000abcd  ,  0000efgh  ==>    abcdefgh
  111.    hex:     $0F     ,    $03     ==>      $F3
  112.  
  113.   (This is the method the Kawai K3 uses to send a byte of data)  }
  114. Begin
  115.   MergeBytes := (Hi shl 4) + (Lo and $0F);
  116. End;
  117.  
  118. Procedure UnMergeBytes( Input:Byte;
  119.                         Var
  120.                           Hi,Lo:Byte);
  121. { Breaks a byte (Input) into 2 bytes, Hi containing the high nibble,
  122.   and Lo containing the low nibble. (reverse of MergeBytes) }
  123. Begin
  124.   Lo := Input and $0F;
  125.   Hi := Input shr 4;
  126. End;
  127.  
  128. Procedure SeeMidiStream;
  129. Var
  130.   MidiDAta:Byte;
  131.   Ch:Char;
  132. Begin
  133.   repeat                               {Begin Loop}
  134.     GetData (MidiData);                {Get MidiData from MPU   }
  135.     if MidiData <> $FE then              {If it's not an active sensing byte}
  136.         write (bin (MidiData),'  ');      {..then write it to the screen     }
  137.     If keyPressed then
  138.     Begin
  139.       Read(kbd,Ch);
  140.       EscAbort:=Ch=#27;
  141.       Write(ch);
  142.     End;
  143.   until EscAbort
  144. End;
  145.  
  146. Procedure CountMidiStream;
  147. Var
  148.   MidiDAta:Byte;
  149.   Ch:Char;
  150.   Count:Integer;
  151. Begin
  152.   Count:=0;
  153.   repeat                               {Begin Loop}
  154.     GetData (MidiData);                {Get MidiData from MPU   }
  155.     if MidiData <> $FE then              {If it's not an active sensing byte}
  156.     Begin
  157.       Count:=Succ(Count);
  158.     end
  159.     Else If Count>0 then
  160.     Begin
  161.       Writeln(Count,' bytes received before $FE.');
  162.       Count:=0;
  163.     End;
  164.     If keyPressed then
  165.     Begin
  166.       Read(kbd,Ch);
  167.       EscAbort:=Ch=#27;
  168.       Write(ch);
  169.     End;
  170.   until EscAbort
  171. End;
  172.  
  173. Procedure UpdatePos(PatchNumber:Byte;UpDated:Boolean);
  174. Var
  175.   Temp,
  176.   Bank,
  177.   X,Y:Integer;
  178. Begin
  179.   Temp := PatchNumber -1;
  180.   Bank := Temp div 50;
  181.   X := 1 + (Temp div 3) * 3;
  182.   Y := 1 + Bank * 11 + ((PatchNumber - 1) mod 3) * 2;
  183.   If UpDated then HighVideo;
  184.   GotoXY(X,Y);
  185.   Write(PatchNumber);
  186.   LowVideo;
  187. End;
  188.  
  189. Procedure RequestDataDump;
  190. Const
  191.   Length=8;{Number of bytes in this request command}
  192.   DumpBankArray : array[1..Length] of Byte = ($F0,$40,$00,$01,$00,$01,$00,$FE);
  193. Var
  194.   I:Integer;
  195. Begin
  196.   For I:=1 to Length do PutData(DumpBankArray[I]);
  197. End;
  198.  
  199. Procedure PutSysExHeader;
  200. Const
  201.   Length=7; {Number of bytes in this request command}
  202.   DumpBankArray : array[1..Length] of Byte = ($F0,$40,$00,$21,$00,$01,$00);
  203. Var
  204.   I:Integer;
  205. Begin
  206.   For I:=1 to Length do PutData(DumpBankArray[I]); {Send SysEx Header}
  207. End;
  208.  
  209. Procedure GetFileName(Var Name:AnyStringType);
  210. {Gets a file name}
  211. Begin
  212.   Write('Enter file name:');
  213.   Readln(Name);
  214. End;
  215.  
  216. Procedure ReadBankFromFile(Var Bank:BankType);
  217. Var
  218.   FileName:AnyStringType;
  219.   BankFile:File of BankType;
  220. Begin
  221.   GetFileName(FileName);
  222.   Assign(BankFile,FileName);
  223.   Reset(BankFile);
  224.   Read(BankFile,Bank);
  225.   Close(Bankfile);
  226. End;
  227.  
  228. Procedure WriteBankToFile(Bank:BankType);
  229. Var
  230.   FileName:AnyStringType;
  231.   BankFile:File of BankType;
  232. Begin
  233.   GetFileName(FileName);
  234.   Assign(BankFile,FileName);
  235.   Rewrite(BankFile);
  236.   Write(BankFile,Bank);
  237.   Close(BankFile);
  238. End;
  239.  
  240. Procedure GetBankFromKeyboard;
  241. {Gets a bank from keyboard and saves it to a file}
  242. Var
  243.   Hi,Lo,
  244.   MidiData:Byte;
  245.   ChkSum,       {note: in THIS procedure, ChkSum is an integer varable}
  246.   Bite,
  247.   Patch:Integer;
  248.   Ch:Char;
  249.   Bank:BankType;
  250. Begin {GetBankFromKeyboard}
  251.   ClrScr;
  252.   RequestDataDump;
  253.   Repeat {Wait for sysex}
  254.     GetData(MidiData);
  255.     If keyPressed then
  256.     Begin
  257.       Read(kbd,Ch);
  258.       EscAbort:=Ch=#27;
  259.       Write(ch);
  260.     End;
  261.   Until EscAbort or ( MidiData=$F0 );
  262.   Info('System Exclusive Received');
  263.   GetData(MidiData); Info('Kawai ID received');
  264.   GetData(MidiData); Info('Midi Channel (0-15) is :'+Int2Str(MidiData) );
  265.   GetData(MidiData); Info('Function Number:'+int2Str(MidiData) );
  266.   GetData(MidiData); Info('Group number is:'+int2Str(MidiData) );
  267.   GetData(MidiData); Info('ID is: '+int2Str(MidiData) );
  268.   GetData(MidiData); Info('SubCommand = $'+hex(MidiData) );
  269.   For Patch:=1 to PatchesPerBank do
  270.   Begin
  271.     ChkSum:=0;
  272.     For Bite:=1 to BytesPerPatch do
  273.     Begin
  274.       GetData(Hi); GetData(Lo);
  275.       Bank[Patch,Bite]:=MergeBytes(Hi,Lo);
  276.       ChkSum:=ChkSum+Bank[Patch,Bite];
  277.     End;
  278.     GetData(Hi); GetData(Lo);
  279.     If (ChkSum and $00FF) <> MergeBytes(Hi,Lo) Then
  280.              Writeln('Patch #',Patch,' did not pass check sum. Data is bad.');
  281.   End;
  282.   GetData(MidiData); If MidiData<>$FE Then
  283.                  Writeln('End of Exclusive not received when expected.');
  284.   Writeln;
  285.   WriteBankToFile(Bank);
  286.   Writeln('Bank saved.');
  287. End;
  288.  
  289. Procedure PutBankToKeyboard;
  290. {Send a bank to keyboard}
  291. Const
  292.   Length=7;{Number of bytes in this request command}
  293.   DumpBankArray : array[1..Length] of Byte = ($F0,$40,$00,$21,$00,$01,$00);
  294. Var
  295.   ChkSum,  {note: in THIS procedure, ChkSum is a byte variable}
  296.   Hi,Lo,
  297.   MidiData:Byte;
  298.   Bite,
  299.   Patch:Integer;
  300.   Ch:Char;
  301.   Bank:BankType;
  302. Begin {PutBankToKeyboard}
  303.   ReadBankFromFile(Bank);
  304.   PutSysExHeader;  For Patch:=1 to PatchesPerBank do
  305.   Begin
  306.     ChkSum:=0;
  307.     GotoXY(1,WhereY); Write(Patch);
  308.     For Bite:=1 to BytesPerPatch do
  309.     Begin
  310.       ChkSum := ChkSum + Bank[Patch,Bite];
  311.       UnMergeBytes( Bank[Patch,Bite], Hi, Lo );
  312.       PutData(Hi);
  313.       PutData(Lo);
  314.     End;
  315.     UnMergeBytes(ChkSum,Hi,Lo);
  316.     PutData(Hi);
  317.     PutData(Lo);
  318.   End;
  319.   PutData($FE); {Send end of exclusive}
  320.   Writeln;
  321.   Writeln('File sent');
  322. End;
  323.  
  324. { **** MAIN PROGRAM **** }
  325. begin
  326.   for J:=1 to 2000 do mididata:=Port[$330];{clear MPU}
  327.   EscAbort:=False;
  328.   LowVideo;
  329.   PutCmd ($3F);                        {Put MPU into UART mode.  }
  330.   Writeln;
  331.   While not EscAbort do
  332.   Begin
  333.     Writeln('To or From keyboard');
  334.     While not keypressed do;
  335.     Read(kbd,Direction);
  336.     Case Upcase(direction) of
  337.       'T':PutBankToKeyboard;
  338.       'F':GetBankFromKeyboard;
  339.       #27:EscAbort:=True;
  340.     End;{case}
  341.   End;{While}
  342.   PutData ($FF);                       {Reset MPU            }
  343. end.